home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
boot
/
czesc_2
/
snap
/
saveilbm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-10
|
5KB
|
238 lines
/* Auto: make
*/
#include <setjmp.h>
#include "Snap.h"
#define SAFE( cond, jmp_buf) { if ( !( cond)) longjmp( jmp_buf,-1); }
IMPORT BYTE TranspBuf[ ];
#define ID( a,b,c,d) ( ( a << 24L) | ( b << 16L) | ( c << 8L) | ( d))
struct ckHdr
{
LONG ChunkName;
LONG ChunkSize;
};
struct SnapBitMapHeader
{
UWORD w, h;
WORD x, y;
UBYTE nPlanes;
UBYTE masking;
UBYTE compression;
UBYTE pad1;
UWORD transparentColor;
UBYTE xAspect, yAspect;
WORD pageWidth, pageHeight;
};
struct ckHdr FORM =
{
ID( 'F', 'O', 'R', 'M'),
0L
};
LONG TYPE = ID( 'I', 'L', 'B', 'M');
struct ckHdr BMHD =
{
ID( 'B', 'M', 'H', 'D'),
sizeof ( struct SnapBitMapHeader)
};
struct SnapBitMapHeader BMHdr =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
struct ckHdr CAMG =
{
ID( 'C', 'A', 'M', 'G'),
4L
};
ULONG ViewMode = NULL;
struct ckHdr CMAP =
{
ID( 'C', 'M', 'A', 'P'),
0L
};
struct ckHdr BODY =
{
ID( 'B', 'O', 'D', 'Y'),
0L
};
UBYTE *buf;
WORD bufcnt;
ULONG totalsize;
WORD bump( struct CBFHandle *CBFH, WORD cnt, UBYTE * dataptr, WORD size)
{
REGISTER LONG tsize = size;
if ( tsize)
{
totalsize += tsize + 1; /* Don't forget the count-byte */
}
if ( bufcnt + tsize + 1 >= 4096 || tsize == 0)
{
if ( CBFWrite( CBFH, ( char *)buf, ( LONG) bufcnt) == -1L)
{
return 0;
}
bufcnt = 0;
}
buf[ bufcnt++] = cnt;
CopyMem( ( char *)dataptr, ( char *)&buf[ bufcnt], tsize);
bufcnt += tsize;
return 1;
}
ULONG WriteBody( BM, CBFH)
struct BitMap *BM;
struct CBFHandle *CBFH;
{
WORD scanline, plane;
REGISTER WORD bpr = BM->BytesPerRow;
REGISTER WORD i, j;
LONG offset = 0L;
REGISTER UBYTE data;
REGISTER UBYTE *bd;
jmp_buf failure;
totalsize = 0L;
if ( !( buf = AllocMem( 4096L, MEMF_PUBLIC)))
{
return NULL;
}
if ( setjmp( failure))
{
FreeMem( buf, 4096L);
return NULL;
}
bufcnt = 0;
for ( scanline = 0; scanline < BM->Rows; ++scanline)
{
for ( plane = 0; plane < BM->Depth; ++plane)
{
bd = BM->Planes[ plane] + offset;
i = 1;
j = bpr - 1;
data = bd[ 0];
while ( j)
{
if ( bd[ i] == data)
{ /* Equal bytes? */
--i; /* First equal byte */
if ( i > 0)
{ /* Old "random" data to save */
SAFE( bump( CBFH, ( WORD) ( i - 1), bd, i), failure);
}
bd = &bd[ i]; /* Start of equal bytes */
i = 2; /* 0 & 1 is equal */
--j;
while ( i < 128 && j && bd[ i] == data)
{
++i;
--j;
}
SAFE( bump( CBFH, ( WORD) - ( i - 1), &bd[ i - 1], ( WORD) 1), failure);
goto new_block;
}
else
{ /* Not equal. Check block range */
if ( i == 128)
{ /* Block limit */
SAFE( bump( CBFH, ( WORD) ( i - 1), bd, i), failure);
new_block:
bd = &bd[ i]; /* Start new block */
i = 0;
if ( j == 0)
{
break;
}
}
}
/* Different byte or a new start */
data = bd[ i]; /* New possible equal */
next_byte:
++i;
--j;
}
if ( i != 0)
{ /* Data to save */
SAFE( bump( CBFH, ( WORD) ( i - 1), bd, i), failure);
}
}
offset += BM->BytesPerRow;
}
/* Flush any bytes left if the buffer */
SAFE( bump( CBFH, ( WORD) 0, NULL, ( WORD) 0), failure);
FreeMem( buf, 4096L);
return totalsize;
}
WORD SaveGS( GS, CBFH)
struct GfxSnap *GS;
struct CBFHandle *CBFH;
{
ULONG BODYPos;
UBYTE *oldtitle;
jmp_buf failure;
oldtitle = GS->window->Title;
SetWindowTitles( GS->window, "Saving...", ( char *)-1);
BMHdr.w = GS->BitMap->BytesPerRow * 8;
BMHdr.h = GS->height;
BMHdr.x = BMHdr.y = 0;
BMHdr.nPlanes = GS->depth;
BMHdr.masking = 0;
BMHdr.compression = 1;
BMHdr.transparentColor = dectoint( TranspBuf);
BMHdr.xAspect = BMHdr.xAspect = 1;
BMHdr.pageWidth = GS->pagew;
BMHdr.pageHeight = GS->pageh;
ViewMode = GS->viewmode;
CMAP.ChunkSize = ( LONG) 3 *( GS->viewmode & HAM ? 16 : 1L << GS->depth);
CBFInit( CBFH);
if ( setjmp( failure))
{
CBFEndWrite( CBFH);
return 0;
}
SAFE( CBFWrite( CBFH, ( char *)&FORM,
( LONG) ( sizeof ( FORM) + sizeof ( TYPE) +
sizeof ( BMHD) + sizeof ( BMHdr) +
sizeof ( CAMG) + sizeof ( ViewMode) +
sizeof ( CMAP))) != -1L, failure);
SAFE( CBFWrite( CBFH, ( char *)GS->rgb, CMAP.ChunkSize) != -1L, failure);
BODYPos = CBFSeek( CBFH, 0L, OFFSET_CURRENT);
SAFE( CBFWrite( CBFH, ( char *)&BODY, ( LONG) sizeof ( BODY)) != -1L, failure);
SAFE( BODY.ChunkSize = WriteBody( GS->BitMap, CBFH), failure);
FORM.ChunkSize = BODYPos - sizeof ( FORM) + sizeof ( BODY) + BODY.ChunkSize;
if ( FORM.ChunkSize & 1)
{ /* Odd size */
SAFE( CBFWrite( CBFH, "X", 1L) != -1L, failure);
++FORM.ChunkSize;
}
CBFSeek( CBFH, 0L, OFFSET_BEGINNING);
CBFWrite( CBFH, ( char *)&FORM, ( LONG) sizeof ( FORM));
CBFSeek( CBFH, BODYPos, OFFSET_BEGINNING);
CBFWrite( CBFH, ( char *)&BODY, ( LONG) sizeof ( BODY));
CBFEndWrite( CBFH);
SetWindowTitles( GS->window, ( char *)oldtitle, ( char *)-1);
return 1;
}